package org.truenewx.tnxjee.webmvc.feign;

import java.io.IOException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;

import org.springframework.context.ApplicationContext;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.GenericFilterBean;
import org.truenewx.tnxjee.model.spec.user.security.UserSpecificDetails;
import org.truenewx.tnxjee.web.util.WebConstants;
import org.truenewx.tnxjee.webmvc.jwt.JwtParser;
import org.truenewx.tnxjee.webmvc.security.authentication.UserSpecificDetailsAuthenticationToken;

/**
 * Feign JWT鉴定过滤器
 */
public class FeignJwtAuthenticationFilter extends GenericFilterBean {

    private JwtParser jwtParser;

    public FeignJwtAuthenticationFilter(ApplicationContext context) {
        this.jwtParser = context.getBean(JwtParser.class);
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        Authentication authentication = securityContext.getAuthentication();

        if (this.jwtParser.isAvailable()) {
            HttpServletRequest request = (HttpServletRequest) req;
            String type = request.getHeader(WebConstants.HEADER_RPC_TYPE);
            String jwt = request.getHeader(WebConstants.HEADER_RPC_JWT);
            UserSpecificDetails<?> details = this.jwtParser.parse(type, jwt, UserSpecificDetails.class);
            if (details != null) {
                securityContext.setAuthentication(new UserSpecificDetailsAuthenticationToken(details));
            }
        }

        chain.doFilter(req, res);

        // 原授权不为空则恢复
        if (authentication != null) {
            securityContext.setAuthentication(authentication);
        }
    }

}
